home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / dnet / dnetsolaris.lzh / server / snfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-12  |  12.6 KB  |  611 lines

  1.  
  2. /*
  3.  *  SNFS.C     V1.1
  4.  *
  5.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  *
  7.  *  NETWORK FILE SYSTEM SERVER
  8.  *
  9.  *  Accepts connections to files or directories & read-write or dir-scan calls.
  10.  */
  11.  
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/wait.h>
  15. #include <sys/time.h>
  16. #include <sys/dir.h>
  17. #include <sys/file.h>
  18. #include <sys/resource.h>
  19. #include <stdio.h>
  20. #include <errno.h>
  21. #include <signal.h>
  22.  
  23. #include "servers.h"
  24. #include "snfs.h"
  25.  
  26. /* #define DEBUG */
  27.  
  28. #define MAXHANDLES    256
  29.  
  30. char *FDName();
  31. extern void AmigaToUnixPath();
  32. extern void ConcatPath();
  33. extern char *malloc();
  34. extern char *TailPart();
  35. extern char *strcpy();
  36.  
  37. int Chan;
  38.  
  39. typedef struct {
  40.     short isopen;
  41.     short fd;
  42.     int   modes;
  43.     int   remodes;
  44.     long  pos;
  45.     char  *name;
  46. } HANDLE;
  47.  
  48. HANDLE Handle[MAXHANDLES];
  49.  
  50.  
  51. chandler()
  52. {
  53.     union wait stat;
  54.     struct rusage rus;
  55.     while (wait3(&stat, WNOHANG, &rus) > 0);
  56. }
  57.  
  58. void NFs();
  59.  
  60. main(ac,av)
  61. char *av[];
  62. {
  63.     long chann = DListen(PORT_NFS);
  64.     int fd;
  65.     int n;
  66.     char buf[1024];
  67.     extern int errno;
  68.  
  69.     if (av[1])
  70.     chdir(av[1]);
  71. #ifdef DEBUG
  72.     freopen("NFS", "w", stderr);
  73.     fprintf(stderr, "RUNNING\n");
  74.     fflush(stderr);
  75. #endif
  76.     signal(SIGCHLD, chandler);
  77.     signal(SIGPIPE, SIG_IGN);
  78.     for (;;) {
  79.     fd = DAccept(chann);
  80.     if (fd < 0)
  81.         break;
  82.     if (fork() == NULL) {
  83.         NFs(fd);
  84. #ifdef DEBUG
  85.         fprintf(stderr, "CLOSING\n");
  86.         fflush(stderr);
  87. #endif
  88.         _exit(1);
  89.     }
  90.     close(fd);
  91.     }
  92. }
  93.  
  94. void
  95. NFs(chan)
  96. int chan;
  97. {
  98.     OpenHandle("/", "", O_RDONLY); /* root */
  99.     for (;;) {
  100.     struct {
  101.         char    cmd;
  102.         unsigned char blen;
  103.         unsigned long dlen;
  104.     } Base;
  105.     long bytes;
  106.     union {
  107.         OpOpen    Open;
  108.         OpRead    Read;
  109.         OpWrite    Write;
  110.         OpClose    Close;
  111.         OpSeek    Seek;
  112.         OpParent    Parent;
  113.         OpDelete    Delete;
  114.         OpCreateDir CreateDir;
  115.         OpDup    Dup;
  116.         OpNextDir   NextDir;
  117.         OpRename    Rename;
  118.     } R;
  119.     union {
  120.         RtOpen    Open;
  121.         RtRead    Read;
  122.         RtWrite    Write;
  123.         RtSeek    Seek;
  124.         RtParent    Parent;
  125.         RtDelete    Delete;
  126.         RtCreateDir CreateDir;
  127.         RtDup    Dup;
  128.         RtNextDir   NextDir;
  129.         RtRename    Rename;
  130.     } W;
  131.     long h;
  132.     char buf[256];
  133.  
  134.     if (ggread(chan, &Base, sizeof(Base)) != sizeof(Base))
  135.         break;
  136. #ifdef DEBUG
  137.         fprintf(stderr, "command %02x %ld %ld\n", 
  138.         Base.cmd, Base.blen, Base.dlen
  139.     );
  140.     fflush(stderr);
  141. #endif
  142.     if (ggread(chan, &R, Base.blen) != Base.blen)
  143.         break;
  144.     switch(Base.cmd) {
  145.     case 'M':    /* create directory */
  146.         {
  147.             ggread(chan, buf, Base.dlen);
  148.         AmigaToUnixPath(buf);
  149.         mkdir(buf, 0777);
  150. #ifdef DEBUG
  151.         fprintf(stderr, "MakeDir %s\n", buf);
  152.             fflush(stderr);
  153. #endif
  154.         }
  155.         R.Open.DirHandle = R.CreateDir.DirHandle;
  156.         /* FALL THROUGH */
  157.     case 'P':
  158.         if (Base.cmd == 'P') {
  159.         char *name = FDName(R.Parent.Handle);
  160.         short i = strlen(name)-1;
  161.  
  162. #ifdef DEBUG
  163.         fprintf(stderr, "Parent Dir of: %s\n", name);
  164.         fflush(stderr);
  165. #endif
  166.  
  167.         if (i >= 0 && name[i] == '/')    /* remove tailing /'s */
  168.             --i;
  169.         if (i < 0) {
  170.             W.Open.Handle = -1;
  171.                 gwrite(chan, &W.Open, sizeof(W.Open));
  172. #ifdef DEBUG
  173.             fprintf(stderr, "NO PARENT\n");
  174.             fflush(stderr);
  175. #endif
  176.             break;
  177.         }
  178.         while (i >= 0 && name[i] != '/')  /* remove name */
  179.             --i;
  180.         while (i >= 0 && name[i] == '/')  /* remove tailing /'s */
  181.             --i;
  182.         ++i;
  183.         if (i == 0) {    /* at root */
  184.             buf[i++] = '/';
  185.         } 
  186.         strncpy(buf, name, i);
  187.         buf[i] = 0;
  188. #ifdef DEBUG
  189.         fprintf(stderr, "Parent Exists: %s\n", buf);
  190.             fflush(stderr);
  191. #endif
  192.             R.Open.DirHandle = 0;
  193.         }
  194.         R.Open.Modes = 1005;
  195.         /* FALL THROUGH */
  196.     case 'O':    /*    open    */
  197.         if (Base.cmd == 'O')  {
  198.             ggread(chan, buf, Base.dlen);
  199.         AmigaToUnixPath(buf);
  200. #ifdef DEBUG
  201.         fprintf(stderr, "OPEN: %s %d\n", buf, Base.dlen);
  202.         fflush(stderr);
  203. #endif
  204.         }
  205.         if (R.Open.Modes == 1006)
  206.             h = OpenHandle(FDName(R.Open.DirHandle),buf, 
  207.             O_CREAT|O_TRUNC|O_RDWR
  208.         );
  209.         else
  210.         h = OpenHandle(FDName(R.Open.DirHandle),buf, O_RDWR);
  211. #ifdef DEBUG
  212.         fprintf(stderr, "Open h = %d name = %s  modes=%d\n", 
  213.         h, buf, R.Open.Modes
  214.         );
  215.         fflush(stderr);
  216. #endif
  217.         if (h >= 0) {
  218.         struct stat stat;
  219.         if (fstat(FDHandle(h), &stat) < 0)
  220.             perror("fstat");
  221.             W.Open.Handle = h;
  222.             W.Open.Prot = 0;
  223.             W.Open.Type = (stat.st_mode & S_IFDIR) ? 1 : -1;
  224. #ifdef DEBUG
  225.         fprintf(stderr, "fstat type %d\n", W.Open.Type);
  226.         fflush(stderr);
  227. #endif
  228.             W.Open.Size = stat.st_size;
  229.         SetDate(&W.Open.Date, stat.st_mtime);
  230.             gwrite(chan, &W.Open, sizeof(W.Open));
  231.         if (Base.cmd == 'P') {    /* tag name */
  232.             char *tail = TailPart(buf);
  233.             unsigned char c = strlen(tail) + 1;
  234.  
  235.             gwrite(chan, &c, 1);
  236.             gwrite(chan, tail, c);
  237.         }
  238.         } else {
  239.         W.Open.Handle = -1;
  240.             gwrite(chan, &W.Open, sizeof(W.Open));
  241.         }
  242.         break;
  243.     case 'N':    /* next directory.  Scan beg. at index    */
  244.         {
  245.         DIR *dir = opendir(FDName(R.NextDir.Handle));
  246.         struct stat sbuf;
  247.         struct direct *dp;
  248.         long index = 0;
  249.         char buf[1024];
  250.  
  251.         while (dir && index <= R.NextDir.Index + 2) {
  252.             if ((dp = readdir(dir)) == NULL)
  253.             break;
  254.             ++index;
  255.         }
  256.         if (dir)
  257.             closedir(dir);
  258.         if (index <= R.NextDir.Index + 2) {
  259.             W.Open.Handle = -1;
  260.         } else {
  261.             W.Open.Handle = index;
  262.             strcpy(buf, FDName(R.NextDir.Handle));
  263.             strcat(buf, "/");
  264.             strcat(buf, dp->d_name);
  265.             stat(buf, &sbuf);
  266.                 W.Open.Prot = 0;
  267.                 W.Open.Type = (sbuf.st_mode & S_IFDIR) ? 1 : -1;
  268. #ifdef DEBUG
  269.             fprintf(stderr, "fstat type %d\n", W.Open.Type);
  270.             fflush(stderr);
  271. #endif
  272.                 W.Open.Size = sbuf.st_size;
  273.             SetDate(&W.Open.Date, sbuf.st_mtime);
  274.         }
  275.         gwrite(chan, &W.Open, sizeof(W.Open));
  276.         if (W.Open.Handle >= 0) {
  277.             unsigned char len = strlen(dp->d_name) + 1;
  278.             gwrite(chan, &len, 1);
  279.             gwrite(chan, dp->d_name, len);
  280.         }
  281.         }
  282.         break;
  283.     case 'r':    /*    RENAME    */
  284.         {
  285.         char tmp1[512];
  286.         char tmp2[512];
  287.         char buf1[1024];
  288.         char buf2[1024];
  289.  
  290.             ggread(chan, buf, Base.dlen);
  291.         strcpy(tmp1, buf);
  292.         strcpy(tmp2, buf + strlen(buf) + 1);
  293.         AmigaToUnixPath(tmp1);
  294.         AmigaToUnixPath(tmp2);
  295.         ConcatPath(FDName(R.Rename.DirHandle1), tmp1, buf1);
  296.         ConcatPath(FDName(R.Rename.DirHandle2), tmp2, buf2);
  297. #ifdef DEBUG
  298.         fprintf(stderr, "Rename %s to %s\n", buf1, buf2);
  299.         fflush(stderr);
  300. #endif
  301.         if (rename(buf1, buf2) < 0)
  302.             W.Rename.Error = 1;
  303.         else
  304.             W.Rename.Error = 0;
  305.         gwrite(chan, &W.Rename.Error, sizeof(W.Rename.Error));
  306.         }
  307.         break;
  308.     case 'd':    /*    DUP    */
  309.         h = DupHandle(R.Dup.Handle);
  310.         if (h >= 0) {
  311.         struct stat stat;
  312.         if (fstat(FDHandle(h), &stat) < 0)
  313.             perror("fstat");
  314.             W.Open.Handle = h;
  315.             W.Open.Prot = 0;
  316.             W.Open.Type = (stat.st_mode & S_IFDIR) ? 1 : -1;
  317. #ifdef DEBUG
  318.         fprintf(stderr, "fstat type %d\n", W.Open.Type);
  319.         fflush(stderr);
  320. #endif
  321.             W.Open.Size = stat.st_size;
  322.         SetDate(&W.Open.Date, stat.st_mtime);
  323.         } else {
  324.         W.Open.Handle = -1;
  325.         }
  326.         gwrite(chan, &W.Dup, sizeof(W.Dup));
  327.         break;
  328.     case 'R':    /*    READ    */
  329.         {
  330.         int fd = FDHandle(R.Read.Handle);
  331.         char *buf = malloc(R.Read.Bytes);
  332.  
  333.         W.Read.Bytes = read(fd, buf, R.Read.Bytes);
  334. #ifdef DEBUG
  335.         fprintf(stderr, "h=%d fd %d Read %d  Result=%d\n", 
  336.             R.Read.Handle, fd, R.Read.Bytes, W.Read.Bytes
  337.         );
  338.             fflush(stderr);
  339. #endif
  340.         gwrite(chan, &W.Read, sizeof(W.Read));
  341.         if (W.Read.Bytes > 0)
  342.             gwrite(chan, buf, W.Read.Bytes);
  343.         free(buf);
  344.         }
  345.         break;
  346.     case 'W':
  347.         {
  348.         int fd = FDHandle(R.Write.Handle);
  349.         char *buf = malloc(R.Write.Bytes);
  350.         if (ggread(chan, buf, R.Write.Bytes) != R.Write.Bytes)
  351.             break;
  352.         W.Write.Bytes = write(fd, buf, R.Write.Bytes);
  353. #ifdef DEBUG
  354.         fprintf(stderr, "h=%d fd %d Write %d  Result=%d\n", 
  355.             R.Write.Handle, fd, R.Write.Bytes, W.Write.Bytes
  356.         );
  357.             fflush(stderr);
  358. #endif
  359.         gwrite(chan, &W.Write, sizeof(W.Write));
  360.         free(buf);
  361.         }
  362.         break;
  363.     case 'C':
  364.         {
  365.         CloseHandle(R.Close.Handle);
  366.         }
  367.         break;
  368.     case 'S':
  369.         {
  370.         int fd = FDHandle(R.Seek.Handle);
  371.         W.Seek.OldOffset = lseek(fd, 0, 1);
  372.         W.Seek.NewOffset = lseek(fd, R.Seek.Offset, R.Seek.How);
  373. #ifdef DEBUG
  374.         fprintf(stderr, "h %d SEEK %d %d %d result = %d\n",
  375.             R.Seek.Handle, fd, R.Seek.Offset, R.Seek.How,
  376.             W.Seek.NewOffset
  377.         );
  378.             fflush(stderr);
  379. #endif
  380.         gwrite(chan, &W.Seek, sizeof(W.Seek));
  381.         }
  382.         break;
  383.     case 'D':
  384.         {
  385.         char buf2[1024];
  386.  
  387.             ggread(chan, buf, Base.dlen);    /* get name to delete */
  388.         AmigaToUnixPath(buf);
  389.         ConcatPath(FDName(R.Delete.DirHandle), buf, buf2);
  390.  
  391.         unlink(buf2);
  392.         rmdir(buf2);
  393. #ifdef DEBUG
  394.         fprintf(stderr, "Delete %s\n", buf2);
  395.             fflush(stderr);
  396. #endif
  397.         W.Delete.Error = 0;
  398.         gwrite(chan, &W.Delete, sizeof(W.Delete));
  399.         }
  400.         break;
  401.     default:
  402.         exit(1);
  403.         break;
  404.     }
  405.     }
  406. }
  407.  
  408. OpenHandle(base, tail, modes)
  409. char *base;
  410. char *tail;
  411. int modes;
  412. {
  413.     short i;
  414.     int fd;
  415.     char name[1024];
  416.  
  417.     ConcatPath(base, tail, name);
  418.     for (i = 0; i < MAXHANDLES; ++i) {
  419.     if (Handle[i].isopen == 0)
  420.         break;
  421.     }
  422.     if (i == MAXHANDLES)
  423.     return(-1);
  424.     fd = open(name, modes, 0666);
  425.     if (fd < 0 && (modes & O_RDWR) && !(modes & O_CREAT)) {
  426.     modes &= ~O_RDWR;
  427.     fd = open(name, modes);
  428.     }
  429.     Handle[i].name = strcpy(malloc(strlen(name)+1), name);
  430.     Handle[i].fd = fd;
  431. #ifdef DEBUG
  432.     fprintf(stderr, "OpenHandle: %d = open %s %d\n", Handle[i].fd, name,modes);
  433.     fflush(stderr);
  434. #endif
  435.     if (Handle[i].fd < 0)
  436.     return(-1);
  437.     Handle[i].modes = modes;
  438.     Handle[i].remodes= modes & ~(O_TRUNC|O_CREAT);
  439.     Handle[i].isopen = 1;
  440.     return(i);
  441. }
  442.  
  443. CloseHandle(h)
  444. {
  445. #ifdef DEBUG
  446.     fprintf(stderr, " Close Handle %d\n", h);
  447.     fflush(stderr);
  448. #endif
  449.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  450.     if (Handle[h].fd >= 0)
  451.         close(Handle[h].fd);
  452.     Handle[h].fd = -1;
  453.     Handle[h].isopen = 0;
  454.     free(Handle[h].name);
  455.     }
  456. }
  457.  
  458. /*
  459.  *  Insert ../ for / at beginning.
  460.  */
  461.  
  462. void
  463. AmigaToUnixPath(buf)
  464. char *buf;
  465. {
  466.     char *base = buf;
  467. #ifdef DEBUG
  468.     fprintf(stderr, "AmigaToUnixPath %s", buf);
  469. #endif
  470.     if (*buf == ':')
  471.     *buf++ = '/';
  472.     while (*buf == '/') {
  473.     bcopy(buf, buf + 2, strlen(buf)+1);
  474.     buf[0] = buf[1] = '.';
  475.     buf += 3;
  476.     }
  477. #ifdef DEBUG
  478.     fprintf(stderr, " TO %s\n", base);
  479.     fflush(stderr);
  480. #endif
  481. }
  482.  
  483. void
  484. ConcatPath(s1, s2, buf)
  485. char *s1, *s2;
  486. char *buf;
  487. {
  488. #ifdef DEBUG
  489.     fprintf(stderr, "ConCatPaths From '%s' '%s'\n", s1, s2);
  490. #endif
  491.     while (strncmp(s2, "../", 3) == 0) {    /* parent */
  492.     ;
  493.     break;
  494.     }
  495.     while (strncmp(s2, "./", 2) == 0) {        /* current */
  496.     s2 += 2;
  497.     }
  498.     if (s2[0] == '/') {
  499.     strcpy(buf, s2);
  500.     return;
  501.     }
  502.     if (s1[0] == 0 && s2[0] == 0) {
  503.     strcpy(buf, ".");
  504.     return;
  505.     }
  506.     if (s1[0] == 0)
  507.     s1 = ".";
  508.     strcpy(buf, s1);
  509.     if (s1[strlen(s1)-1] != '/')
  510.         strcat(buf, "/");
  511.     strcat(buf, s2);
  512. #ifdef DEBUG
  513.     fprintf(stderr, "ConCatPaths to %s\n", buf);
  514.     fflush(stderr);
  515. #endif
  516. }
  517.  
  518. char *
  519. FDName(h)
  520. {
  521. #ifdef DEBUG
  522.     fprintf(stderr, "FDName(%d) =", h);
  523. #endif
  524.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  525. #ifdef DEBUG
  526.     fprintf(stderr, "%s\n", Handle[h].name);
  527.         fflush(stderr);
  528. #endif
  529.     return(Handle[h].name);
  530.     }
  531. #ifdef DEBUG
  532.     fprintf(stderr, "??\n");
  533.     fflush(stderr);
  534. #endif
  535.     return(".");
  536. }
  537.  
  538. DupHandle(h)
  539. {
  540.     short n = -1;
  541.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen)
  542.     n = OpenHandle(".",Handle[h].name, Handle[h].remodes & ~O_RDWR);
  543.     return(n);
  544. }
  545.  
  546. FDHandle(h)
  547. {
  548.     int fd = -1;
  549.     if (h >= 0 && h < MAXHANDLES && Handle[h].isopen) {
  550.     fd = Handle[h].fd;
  551.     if (fd < 0) {
  552.         Handle[h].fd = fd = open(Handle[h].name, Handle[h].remodes, 0666);
  553.         if (fd >= 0 && !(Handle[h].modes & O_APPEND))
  554.         lseek(fd, Handle[h].pos, 0);
  555.     }
  556.     }
  557.     return(fd);
  558. }
  559.  
  560. char *
  561. TailPart(path)
  562. char *path;
  563. {
  564.     register char *ptr = path + strlen(path) - 1;
  565.  
  566.     while (ptr >= path && *ptr != '/')
  567.     --ptr;
  568.     ++ptr;
  569. #ifdef DEBUG
  570.     fprintf(stderr, "TAILPART '%s' -> %s\n", path, ptr);
  571.     fflush(stderr);
  572. #endif
  573.     return(ptr);
  574. }
  575.  
  576. SetDate(date, mtime)
  577. STAMP *date;
  578. time_t mtime;
  579. {
  580.     struct tm *tm = localtime(&mtime);
  581.     long years = tm->tm_year;    /* since 1900    */
  582.     long days;
  583.  
  584.     years += 300;            /* since 1600           */
  585.     days = (years / 400) * 146097;    /* # days every four cents    */
  586.  
  587.     years = years % 400;
  588.  
  589.     /*
  590.      *    First assume a leap year every 4 years, then correct for centuries.
  591.      *    never include the 'current' year in the calculations.  Thus, year 0
  592.      *      (a leap year) is included only if years > 0.
  593.      */
  594.  
  595.     days += years * 365 + ((years+3) / 4);
  596.     
  597.     if (years <= 100)
  598.     ;
  599.     else if (years <= 200)        /* no leap 3 of 4 cent. marks    */
  600.     days -= 1;
  601.     else if (years <= 300)
  602.     days -= 2;
  603.     else
  604.     days -= 3;
  605.     days -= 138062;            /* 1600 -> 1978            */
  606.     date->ds_Days  = days + tm->tm_yday;
  607.     date->ds_Minute= tm->tm_min + tm->tm_hour * 60;
  608.     date->ds_Tick  = tm->tm_sec * 50;
  609. }
  610.  
  611.